/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - graphics/shaders
// Copyright( c) 2014.  All Rights Reserved
//
// File:		AEShaderConstantTable.cpp
// Author:		Gianluca Belardelli
// Date:		30/01/2015
//
/////////////////////////////////////////////////////////////////////////
#include <AEEngine.h>

void AEShaderConstantTable::AllocateEntries( AEINT32 nCount )
{
	if( m_lpEntry )
	{
		AEngine::GetMemManager()->GetHeapAllocator().BlockFree( m_lpEntry, m_nEntryCount*sizeof( AEShaderConstantTableEntry ) );
		AEngine::GetMemManager()->GetHeapAllocator().BlockFree( m_lpBuffer, m_nEntryCount*sizeof( AEFLOAT32 ) );
	}

	//m_nFirstRegister = nFirstReg;
	m_nEntryCount = nCount;

	m_lpEntry = (AEShaderConstantTableEntry *)AEngine::GetMemManager()->GetHeapAllocator().BlockAlloc( m_nEntryCount*sizeof( AEShaderConstantTableEntry ) );
	m_lpBuffer = (AEFLOAT32 *)AEngine::GetMemManager()->GetHeapAllocator().BlockAlloc( m_nEntryCount*sizeof( AEFLOAT32 ) );

	for( AEINT32 i=0; i<m_nEntryCount; i++ )
	{
		AEShaderConstantTableEntry sctEntry;
		memcpy( &m_lpEntry[i], &sctEntry, sizeof( AEShaderConstantTableEntry ) );
	}
}

void AEShaderConstantTable::GetRegisterRange( AEINT32 &nFirst, AEINT32 &nLast ) const
{
	nFirst = m_nFirstRegister;
	AEINT32 nSum = 0;
	for( AEINT32 i=0; i<m_nEntryCount; i++ )
	{
		AEShaderConstantTableEntry *lpEntry = &m_lpEntry[i];
		nSum += lpEntry->GetRegisterCount();
	}

	nLast = m_nFirstRegister + nSum;
}

AEINT32 AEShaderConstantTable::GetMaxSamplerIndex( void ) const
{
	AEINT32 nMax = -1;
	for( AEINT32 i=0; i<m_nEntryCount; i++ )
	{
		AEShaderConstantTableEntry *lpEntry = &m_lpEntry[i];
		if( lpEntry->IsSamplerType() )
		{
			if( lpEntry->nRegisterIndex > nMax )
				nMax = lpEntry->nRegisterIndex;
		}
	}

	return nMax;
}

AEShaderConstantTableEntry *AEShaderConstantTable::FindSamplerWithIndex( AEINT32 nSampler ) const
{
	for( AEINT32 i=0; i<m_nEntryCount; i++ )
	{
		AEShaderConstantTableEntry *lpEntry = &m_lpEntry[i];
		if( lpEntry->IsSamplerType() )
		{
			if( lpEntry->nRegisterIndex == nSampler )
				return lpEntry;
		}
	}

	return AENULL;
}

AE_DLLIMPEXP AEBOOL32 AEShaderConstantTable::AddEntry( AEINT32 nSlot, AEShaderConstantTableEntry *lpEntry )
{
	AEASSERT_MSG( m_nEntryCount > 0, "AEShaderConstantTable::AddEntry Tabella non allocata." );
	AEASSERT_MSG( nSlot <= m_nEntryCount, "AEShaderConstantTable::AddEntry Indice troppo grande." );

	if( *(&m_lpEntry[nSlot].nRegisterIndex) == -1 )
	{
		memcpy( &m_lpEntry[nSlot], lpEntry, sizeof(AEShaderConstantTableEntry) );
		return AETRUE;
	}

	return AEFALSE;
}

AEShaderConstantTableEntry *AEShaderConstantTable::FindByName( const char *lpVarName ) const
{
	for( AEINT32 i=0; i<m_nEntryCount; i++ )
	{
		if( memcmp( &m_lpEntry[i], lpVarName, MAX_CONSTANT_NAMELEN ) )
			return &m_lpEntry[i];
	}

	return AENULL;
}

AEINT32 AEShaderConstantTable::GetSamplerIndexByName( const char *lpSamplerName ) const
{
	for( AEINT32 i=0; i<m_nEntryCount; i++ )
	{
		AEShaderConstantTableEntry *lpEntry = &m_lpEntry[i];
		if( lpEntry->IsSamplerType() )
		{
			if( !strcmp( lpEntry->szVarname, lpSamplerName ) )
				return lpEntry->nRegisterIndex;
		}
	}

	return -1;
}

AEShaderConstantTableEntry *AEShaderConstantTable::FindByStartRegister( AEINT32 nStartReg ) const
{
	for( AEINT32 i=0; i<m_nEntryCount; i++ )
	{
		AEShaderConstantTableEntry *lpEntry = &m_lpEntry[i];
		if( lpEntry->nRegisterIndex == nStartReg)
			return lpEntry;
	}

	return AENULL;
}

AEINT32 AEShaderConstantTable::GetNumEntries (void) const
{
	return m_nEntryCount;
}

const AEShaderConstantTableEntry *AEShaderConstantTable::GetEntry( AEINT32 nEntry ) const
{
	AEASSERT_MSG( nEntry <= m_nEntryCount, "AEShaderConstantTable::GetEntry Indice errato" );
	return ( &m_lpEntry[nEntry] );
}

AEShaderConstantTableEntry *AEShaderConstantTable::GetEntry( AEINT32 nEntry)
{
	AEASSERT_MSG( nEntry <= m_nEntryCount, "AEShaderConstantTable::GetEntry Indice errato" );
	return ( &m_lpEntry[nEntry] );
}
